home *** CD-ROM | disk | FTP | other *** search
- #import "NiftyMatrix.h"
- #import "MultiView.h"
- #import <math.h>
-
- @implementation MultiView
-
- - initFrame:(const NXRect *)frm
- {
- [super initFrame:frm];
- sel_list = [matrix getSelectedCells:nil];
- num = [sel_list count];
- if (num > MAX_VIEWS) num = MAX_VIEWS;
- currentLay = 0;
- [self initLayouts];
- return self;
- }
-
- //
- // deal with defaults
- //
-
- - readDefaults
- {
- int i = 0, j;
- char *def;
- const char *tmp;
- char *current;
-
- tmp = NXGetDefaultValue([NXApp appName],"MultiViews");
- if (tmp) {
- def = malloc(strlen(tmp) + 1);
- strcpy (def,tmp);
- while (def) {
- current = rindex(def,':');
- if (!current) {
- views[i] = [self viewNamed:def];
- j = [self cellNamed:def];
- [matrix setSelectionFrom:j to:j anchor:j lit:YES];
- break;
- }
- views[i] = [self viewNamed:(current+1)];
- i++;
- j = [self cellNamed:(current+1)];
- [matrix setSelectionFrom:j to:j anchor:j lit:YES];
- *current = '\0';
- }
- free(def);
- }
- tmp = NXGetDefaultValue([NXApp appName],"MultiLayout");
- if (tmp)
- currentLay = atoi(tmp);
- printf("%s : %d\n",tmp,currentLay);
- return self;
- }
-
- - writeDefaults:sender
- {
- int i;
- const char *name;
- char def[1024]; // more than we should ever need
-
- if (num > 0) {
- def[0] = '\0';
- for (i = 0; i < num; i++) {
- if (i)
- strcat(def,":");
- name = [[sel_list objectAt:i] stringValue];
- strcat(def,name);
- }
- NXWriteDefault([NXApp appName], "MultiViews", def);
- }
- sprintf(def,"%d",currentLay);
- NXWriteDefault([NXApp appName], "MultiLayout",def);
- return self;
- }
-
-
- //
- // whenever we receive a newWindow message, it's a good time to
- // check the list and reinitialize everything
- // this method is called internally everytime a new selection is made
- - newWindow
- {
- int i, n, lays;
- int x,y,w,h;
- NXRect frm;
-
- // clean up all of the old views. reset their origins
- NXSetRect(&frm,0,0,50,50);
- for (i = 0; i < num; i++)
- [[views[i] setFrame:&frm] removeFromSuperview];
-
- // clean up the screen... what a mess!
- [self display];
- // [self lockFocus];
- // [self drawSelf:&frame :1];
- // [self unlockFocus];
-
- // find out what was selected, and get the appropriate views
- sel_list = [matrix getSelectedCells:nil];
- num = [sel_list count];
- lays = lay_defs[currentLay].num;
- n = MIN(lays,num);
- num = n;
- for (i = 0; i < n; i++) {
- views[i] = [self viewFrom:[sel_list objectAt:i]];
- if (NX_X(&lay_defs[currentLay].pos[i]) == 0)
- x = 0;
- else
- x = NX_WIDTH(&frame) / NX_X(&lay_defs[currentLay].pos[i]);
- if (NX_Y(&lay_defs[currentLay].pos[i]) == 0)
- y = 0;
- else
- y = NX_HEIGHT(&frame) / NX_Y(&lay_defs[currentLay].pos[i]);
- w = NX_WIDTH(&frame) / NX_WIDTH(&lay_defs[currentLay].pos[i]);
- h = NX_HEIGHT(&frame) / NX_HEIGHT(&lay_defs[currentLay].pos[i]);
- NXSetRect(&frm,x,y,w,h);
- [[views[i] setFrame:&frm] setClipping:YES];
- [self addSubview:views[i]];
- // we need to make sure that they draw themselves once first
- // [views[i] lockFocus];
- [views[i] display];
- // [views[i] unlockFocus];
- }
- return self;
- }
-
-
- //
- // rather than call oneStep on every method at once,
- // just call it on one, then next time, call it on the next one.
- // for some reason, this seemed to improve performance
- // (I'm not sure why though)
- //
- - oneStep
- {
- static int cur = 0;
- [views[cur] lockFocus];
- // this is necessary for some views (such as Space) to function properly
- if ([views[cur] respondsTo:@selector(didLockFocus)])
- [views[cur] didLockFocus];
- [views[cur] oneStep];
- [views[cur] unlockFocus];
- cur++;
- if (cur >= num)
- cur = 0;
- return self;
- }
-
-
- //
- // when this is called, we know that we've just been loaded up
- // so we take advantage of that fact and do a lot of initialization
- //
- - inspector:sender
- {
- char buf[MAXPATHLEN];
- NXRect frm, scrollRect;
- NXSize matSize, cellSize;
-
- thinker = sender;
- pub = (struct thinkerDef *)thinker;
- modList = pub->moduleList;
- if (!inspectorPanel)
- {
- //
- // Time to make the matrix... time to make the matrix
- //
- sprintf(buf,"%s/Multi.nib",(char *)[sender moduleDirectory:"Multi"]);
- [NXApp loadNibFile:buf owner:self withNames:NO];
- [scrollView getFrame:&frm];
- matrix = [[NiftyMatrix alloc] initFrame:&frm
- mode:NX_LISTMODE
- cellClass:[Cell class]
- numRows:0
- numCols:1];
- [self fillMatrix];
- [scrollView getFrame:&scrollRect];
- [ScrollView getContentSize:&matSize
- forFrameSize:&scrollRect.size
- horizScroller:NO
- vertScroller:YES
- borderType:NX_BEZEL];
- [matrix getCellSize:&cellSize];
- cellSize.width = matSize.width;
- [matrix setCellSize:&cellSize];
- [matrix sizeToCells];
- [matrix setAutosizeCells:YES];
- [matrix setAutoscroll:YES];
- [scrollView setDocView:matrix];
- [[matrix superview] setAutoresizeSubviews:YES];
- [matrix setAutosizing:NX_WIDTHSIZABLE];
- [matrix setTarget:self];
- [matrix setAction:@selector(select:)];
- [matrix setDoubleAction:@selector(inspect:)];
- [self readDefaults];
- //
- // time to make the funky layout thingie
- //
- // yuck... there must be a better way to initialize arrays like this
- layouts[0] = lay1;
- layouts[1] = lay2;
- layouts[2] = lay3;
- layouts[3] = lay4;
- layouts[4] = lay5;
- layouts[5] = lay6;
- layouts[6] = lay7;
- layouts[7] = lay8;
- layouts[8] = lay9;
- layouts[9] = lay10;
- layouts[10] = lay11;
-
- [layouts[currentLay] getFrame:&frm];
- NXSetRect(&frm,0,0,NX_WIDTH(&frm),NX_HEIGHT(&frm));
- [layouts[currentLay] setFrame:&frm];
- [[layout addSubview:layouts[currentLay]] display];
- }
- return inspectorPanel;
- }
-
-
- //
- // clean up the "multi inspector"
- //
- - inspectorWillBeRemoved
- {
- int i;
- NXRect foo;
- NXSetRect(&foo,0,0,0,0);
- for (i = 0; i < num; i++)
- [views[i] setFrame:&foo];
- if (otherInspector)
- [otherInspector close];
- return self;
- }
-
- - setImage:image
- {
- int i;
- for (i = 0; i < num; i++)
- if ([views[i] respondsTo:@selector(setImage:)])
- [views[i] setImage:image];
- return self;
- }
-
- //
- // helper function to -fillMatrix
- //
- - addCellWithString:(const char *)str at:(int)row
- {
- id theCell;
-
- [matrix insertRowAt:row];
- theCell = [matrix cellAt:row :0];
- [theCell setStringValue:str];
- return self;
- }
-
- //
- // fill the matrix with the view names
- ///
- - fillMatrix
- {
- int i, n, j;
-
- n = [modList count];
- for (i = j = 0; i < n; i++)
- {
- if (strcmp([modList nameAt: i], "Multi"))
- #ifdef MULTI_LOCALIZED
- [self addCellWithString:NXLocalString([modList nameAt: i], 0, 0)
- #else
- [self addCellWithString:[modList nameAt:i]
- #endif
- at:(j++)];
- }
- return self;
- }
-
- //
- // called whenever an item in the matrix is clicked on
- //
- - select:sender
- {
- [self newWindow];
- [[self window] flushWindow];
- return self;
- }
-
-
- //
- // funky layout selection interface code
- //
-
- - layoutUp:sender
- {
- NXRect frm;
- [layouts[currentLay] removeFromSuperview];
- currentLay --;
- if (currentLay < 0)
- currentLay = 10;
- [layouts[currentLay] getFrame:&frm];
- NXSetRect(&frm,0,0,NX_WIDTH(&frm),NX_HEIGHT(&frm));
- [layouts[currentLay] setFrame:&frm];
- [[layout addSubview:layouts[currentLay]] display];
- [self newWindow];
- [[self window] flushWindow];
- return self;
- }
-
- - layoutDown:sender
- {
- NXRect frm;
- [layouts[currentLay] removeFromSuperview];
- currentLay ++;
- if (currentLay > 10)
- currentLay = 0;
- [layouts[currentLay] getFrame:&frm];
- NXSetRect(&frm,0,0,NX_WIDTH(&frm),NX_HEIGHT(&frm));
- [layouts[currentLay] setFrame:&frm];
- [[layout addSubview:layouts[currentLay]] display];
- [self newWindow];
- [[self window] flushWindow];
- return self;
- }
-
- //
- // initialize all of the layout definitions.
- // this is ugly because it's all hardcoded. If I ever mess with the
- // layouts in the interface, I'll also have to change this. Unfortunately,
- // I didn't see a straightforward way of doing it automatically from the drawn
- // layouts. Maybe I should do it the other way, and draw the layouts by hand.
- // that probably makes sense if I ever do any future development on this
- //
- - initLayouts
- {
- lay_defs[0].num = 1;
- [self allocLayout:0];
- NXSetRect(&lay_defs[0].pos[0],0,0,1,1);
- lay_defs[1].num = 2;
- [self allocLayout:1];
- NXSetRect(&lay_defs[1].pos[0],0,2,1,2);
- NXSetRect(&lay_defs[1].pos[1],0,0,1,2);
- lay_defs[2].num = 2;
- [self allocLayout:2];
- NXSetRect(&lay_defs[2].pos[0],0,0,2,1);
- NXSetRect(&lay_defs[2].pos[1],2,0,2,1);
- lay_defs[3].num = 3;
- [self allocLayout:3];
- NXSetRect(&lay_defs[3].pos[0],0,0,2,1);
- NXSetRect(&lay_defs[3].pos[1],2,2,2,2);
- NXSetRect(&lay_defs[3].pos[2],2,0,2,2);
- lay_defs[4].num = 3;
- [self allocLayout:4];
- NXSetRect(&lay_defs[4].pos[0],0,0,2,2);
- NXSetRect(&lay_defs[4].pos[1],0,2,2,2);
- NXSetRect(&lay_defs[4].pos[2],2,0,2,1);
- lay_defs[5].num = 3;
- [self allocLayout:5];
- NXSetRect(&lay_defs[5].pos[0],0,2,1,2);
- NXSetRect(&lay_defs[5].pos[1],0,0,2,2);
- NXSetRect(&lay_defs[5].pos[2],2,0,2,2);
- lay_defs[6].num = 3;
- [self allocLayout:6];
- NXSetRect(&lay_defs[6].pos[0],0,0,1,2);
- NXSetRect(&lay_defs[6].pos[1],0,2,2,2);
- NXSetRect(&lay_defs[6].pos[2],2,2,2,2);
- lay_defs[7].num = 4;
- [self allocLayout:7];
- NXSetRect(&lay_defs[7].pos[0],0,0,2,2);
- NXSetRect(&lay_defs[7].pos[1],2,2,2,2);
- NXSetRect(&lay_defs[7].pos[2],0,2,2,2);
- NXSetRect(&lay_defs[7].pos[3],2,0,2,2);
- lay_defs[8].num = 6;
- [self allocLayout:8];
- NXSetRect(&lay_defs[8].pos[0],0,0,2,3);
- NXSetRect(&lay_defs[8].pos[1],2,0,2,3);
- NXSetRect(&lay_defs[8].pos[2],0,3,2,3);
- NXSetRect(&lay_defs[8].pos[3],2,3,2,3);
- NXSetRect(&lay_defs[8].pos[4],0,1.5,2,3);
- NXSetRect(&lay_defs[8].pos[5],2,1.5,2,3);
- lay_defs[9].num = 6;
- [self allocLayout:9];
- NXSetRect(&lay_defs[9].pos[0],0,0,3,2);
- NXSetRect(&lay_defs[9].pos[1],3,0,3,2);
- NXSetRect(&lay_defs[9].pos[2],1.5,0,3,2);
- NXSetRect(&lay_defs[9].pos[3],0,2,3,2);
- NXSetRect(&lay_defs[9].pos[4],3,2,3,2);
- NXSetRect(&lay_defs[9].pos[5],1.5,2,3,2);
- lay_defs[10].num = 9;
- [self allocLayout:10];
- NXSetRect(&lay_defs[10].pos[0],0,0,3,3);
- NXSetRect(&lay_defs[10].pos[1],3,3,3,3);
- NXSetRect(&lay_defs[10].pos[2],1.5,1.5,3,3);
- NXSetRect(&lay_defs[10].pos[3],0,3,3,3);
- NXSetRect(&lay_defs[10].pos[4],3,0,3,3);
- NXSetRect(&lay_defs[10].pos[5],0,1.5,3,3);
- NXSetRect(&lay_defs[10].pos[6],1.5,0,3,3);
- NXSetRect(&lay_defs[10].pos[7],3,1.5,3,3);
- NXSetRect(&lay_defs[10].pos[8],1.5,3,3,3);
- return self;
- }
-
- - allocLayout:(int)index
- {
- int n;
- n = lay_defs[index].num;
- lay_defs[index].pos = malloc(sizeof(NXRect) * n);
- return self;
- }
-
- //
- // BackSpace Thinker emulation code
- //
-
-
- - performMethodOnViews:(SEL)sel
- {
- int i;
- for (i = 0; i < num; i++)
- if ([views[i] respondsTo:sel])
- [views[i] perform:sel];
- return self;
- }
-
- - enteredScreenSaverMode
- {
- [self performMethodOnViews:@selector(enteredScreenSaverMode)];
- return self;
- }
-
- - willExitScreenSaverMode
- {
- [self performMethodOnViews:@selector(willExitScreenSaverMode)];
- return self;
- }
-
- - inspect:sender
- {
- id insp = nil;
- NXRect frm;
-
- if ([[self viewFrom:sender] respondsTo:@selector(inspector:)])
- insp = [[self viewFrom:sender] inspector:thinker];
- if (insp == nil)
- insp = [thinker nullInspector];
- [insp getFrame:&frm];
- [otherInspector setContentView:insp];
- [otherInspector makeKeyAndOrderFront:self];
- [otherInspector sizeWindow:NX_WIDTH(&frm) :NX_HEIGHT(&frm)];
- [[otherInspector contentView] display];
- return self;
- }
-
-
- //
- // these methods walk the list of views to match names and cells with
- // the views that go with them
- //
-
- - viewFrom:sender
- {
- const char *name;
- int i, n;
- id view = nil;
-
- name = [sender stringValue];
- n = [modList count];
- for (i = 0; i < n; i++)
- if (!strcmp([modList nameAt: i], name))
- view = [modList viewAt: i];
- if (view == nil)
- view = [self loadView:name];
- if (view == nil)
- fprintf(stderr,"returned nil: %s\n",name);
- return view;
- }
-
- - viewNamed:(const char *)name
- {
- int i, n;
- id view = nil;
-
- n = [modList count];
- for (i = 0; i < n; i++)
- if (!strcmp([modList nameAt: i], name))
- view = [modList viewAt: i];
- if (!view)
- view = [self loadView:name];
- return view;
- }
-
- - objectNamed:(const char *)name
- {
- int i, n;
- n = [modList count];
- for (i = 0; i < n; i++)
- if (!strcmp([modList nameAt: i], name))
- return [modList objectAt: i];
- return nil;
- }
-
- - (int)cellNamed:(const char *)name
- {
- int i, n;
-
- n = [matrix cellCount];
- for (i = 0; i < n; i++)
- if (!strcmp([[matrix cellAt: i :0] stringValue], name))
- return i;
- return -1;
- }
-
- // this is pretty much a duplicate of - backView from ThinkMore.m
- // I couldn't just call that directly because it relies on its own state
- // to know what view to load
- - loadView:(const char *)name
- {
- NXRect aFrame = {{0,0},{200,200}};
- id theView = nil;
- char path[MAXPATHLEN];
- id myClass;
- char *filenames[] = {path, NULL};
- ModuleInfo *mp;
- struct mach_header *header;
-
- //if (index(name,' '))
- // name = strip_spaces(name);
- mp = [self objectNamed:name];
- if ([mp path]) {
- long ret;
- while (1)
- {
- sprintf(path, "%s/%sView.BackO", [mp path], name);
- ret = objc_loadModules(filenames, NULL, NULL, &header, NULL);
- if (ret && [mp respondsTo:@selector(useNextPath)])
- if ([mp useNextPath])
- continue;
- break;
- }
- if (ret)
- {
- NXRunAlertPanel([NXApp appName], NXLocalString("Could not dynamically load class: %sView",0,0),
- NULL, NULL, NULL, name);
- return nil;
- }
- else
- {
- [mp setHeader:header];
- }
- //at this point we must have a valid name for a loaded class
- }
- sprintf(path,"%sView", name);
- myClass = objc_getClass(path);
-
- // heh... god I love @defs! :-)
- theView = [[myClass allocFromZone:pub->backZone] initFrame:&aFrame];
- [mp setView:theView];
- // fake 'em out by passing thinker instead of self
- if ([theView respondsTo:@selector(inspector:)])
- [theView inspector:thinker];
-
- return theView;
- }
-
- - drawSelf:(const NXRect *)frm :(int)count
- {
- PSsetgray(0.0);
- NXRectFillList(frm,count);
- return self;
- }
-
- - (BOOL)useBufferedWindow
- {
- return YES;
- }
-
- - (const char *)windowTitle
- {
- return "MultiView";
- }
-
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- [super sizeTo:width :height];
- [self newWindow];
- return self;
- }
-
- //
- // handoff methods... these all just call the equivalent in Thinker
- // some of the modules depend on them
- //
-
- - commonImageInspector
- {
- return [thinker commonImageInspector];
- }
-
- - nullInspector
- {
- return [thinker nullInspector];
- }
-
- - spaceInspector
- {
- return [thinker spaceInspector];
- }
-
- - boinkInspector
- {
- return [thinker boinkInspector];
- }
-
- - (const char *)moduleDirectory:(const char *)name
- {
- return [thinker moduleDirectory:name];
- }
-
-
- @end
-